package cn.iocoder.yudao.module.alipay.didi.client.impl;

import cn.iocoder.yudao.module.alipay.didi.client.UnionClient;
import cn.iocoder.yudao.module.alipay.didi.common.Constants;
import cn.iocoder.yudao.module.alipay.didi.enums.LinkType;
import cn.iocoder.yudao.module.alipay.didi.enums.OrderMockType;
import cn.iocoder.yudao.module.alipay.didi.enums.OrderType;
import cn.iocoder.yudao.module.alipay.didi.enums.PwdType;
import cn.iocoder.yudao.module.alipay.didi.errors.BizError;
import cn.iocoder.yudao.module.alipay.didi.errors.ParamError;
import cn.iocoder.yudao.module.alipay.didi.errors.SystemError;
import cn.iocoder.yudao.module.alipay.didi.models.*;
import com.google.gson.Gson;
import org.slf4j.Logger;

import java.util.TreeMap;

public class UnionClientImpl extends BasicClientImpl implements UnionClient {

    private static final Logger LOGGER = Constants.dunionClientLogger;

    private final DunionClientConfig dunionClientConfig;

    private static final String linkPath = "https://union.didi.cn/openapi/v1.0/link/generate";
    private static final String codePath = "https://union.didi.cn/openapi/v1.0/code/generate";
    private static final String posterPath = "https://union.didi.cn/openapi/v1.0/poster/generate";
    private static final String exchangePwdPath = "https://union.didi.cn/openapi/v1.0/exchange/pwd/generate";
    private static final String orderListPath = "https://union.didi.cn/openapi/v1.0/order/list";
    private static final String orderMockPath = "https://union.didi.cn/openapi/v1.0/orderMock/callback";
    private static final String orderSelfQueryPath = "https://union.didi.cn/openapi/v1.0/order/selfQuery";

    public UnionClientImpl(DunionClientConfig dunionClientConfig) {
        this.dunionClientConfig = dunionClientConfig;
    }

    @Override
    public Result<LinkResponse> generateH5Link(long activityId, long promotionId, String sourceId, int timeout) {
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("activity_id", activityId);
            params.put("promotion_id", promotionId);
            params.put("source_id", sourceId);
            params.put("link_type", LinkType.H5.getValue());
            String resultStr = doPost(dunionClientConfig, linkPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                LinkResponse model = new Gson().fromJson(resultStr, LinkResponse.class);
                return Result.Builder.<LinkResponse> builder().success(true).model(model).build();
            }
            LOGGER.error("generateH5Link fail");
            return Result.Builder.<LinkResponse> builder().success(false).error(new SystemError("generateH5Link fail")).model(null).build();
        }catch (Exception e){
            LOGGER.error("generateH5Link error:{}", e.getMessage());
            return Result.Builder.<LinkResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }
    }

    @Override
    public Result<LinkResponse> generateMiniLink(long activityId, long promotionId, String sourceId, int timeout) {
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("activity_id", activityId);
            params.put("promotion_id", promotionId);
            params.put("source_id", sourceId);
            params.put("link_type", LinkType.Mini.getValue());
            String resultStr = doPost(dunionClientConfig, linkPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                LinkResponse model = new Gson().fromJson(resultStr, LinkResponse.class);
                return Result.Builder.<LinkResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("generateMiniLink fail");
            return Result.Builder.<LinkResponse> builder().success(false).error(new SystemError("generateMiniLink fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generateMiniLink error:{}", e.getMessage());
            return Result.Builder.<LinkResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<QrCodeResponse> generateH5Code(String dsi, String sourceId, int timeout) {
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("dsi", dsi);
            params.put("source_id", sourceId);
            params.put("type", LinkType.H5.getValue());

            String resultStr = doGet(dunionClientConfig, codePath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                QrCodeResponse model = new Gson().fromJson(resultStr, QrCodeResponse.class);
                return Result.Builder.<QrCodeResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("generateH5Code fail");
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new SystemError("generateH5Code fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generateH5Code error:{}", e.getMessage());
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<QrCodeResponse> generateMiniCode(String dsi, String sourceId, int timeout) {
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("dsi", dsi);
            params.put("source_id", sourceId);
            params.put("type",  LinkType.Mini.getValue());

            String resultStr = doGet(dunionClientConfig, codePath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                QrCodeResponse model = new Gson().fromJson(resultStr, QrCodeResponse.class);
                return Result.Builder.<QrCodeResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("generateMiniCode fail");
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new SystemError("generateMiniCode fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generateMiniCode error:{}", e.getMessage());
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<PosterResponse> generatePoster(String dsi, String sourceId, int timeout){
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("dsi", dsi);
            params.put("source_id", sourceId);

            String resultStr = doGet(dunionClientConfig, posterPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                PosterResponse model = new Gson().fromJson(resultStr, PosterResponse.class);
                return Result.Builder.<PosterResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("generatePoster fail");
            return Result.Builder.<PosterResponse> builder().success(false).error(new SystemError("generatePoster fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generatePoster error:{}", e.getMessage());
            return Result.Builder.<PosterResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<ExchangePwdResponse> generateCouponPwd(long activityId, long promotionId, String sourceId, int timeout){
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("activity_id", activityId);
            params.put("promotion_id", promotionId);
            params.put("source_id", sourceId);
            params.put("pwd_type", PwdType.Coupon.getValue());
            String resultStr = doGet(dunionClientConfig, exchangePwdPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                ExchangePwdResponse model = new Gson().fromJson(resultStr, ExchangePwdResponse.class);
                return Result.Builder.<ExchangePwdResponse> builder().success(true).model(model).build();
            }
            LOGGER.error("generateCouponPwd fail");
            return Result.Builder.<ExchangePwdResponse> builder().success(false).error(new SystemError("generateCouponPwd fail")).model(null).build();
        }catch (Exception e){
            LOGGER.error("generateCouponPwd error:{}", e.getMessage());
            return Result.Builder.<ExchangePwdResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }
    }

    @Override
    public Result<QrCodeResponse> generateH5CodeDirectly(long activityId, long promotionId, String sourceId, int timeout) {
        try {
            Result<LinkResponse> linkResult =  this.getLinkResult(activityId, promotionId, sourceId, timeout);
            if(linkResult != null && linkResult.getModel() != null && linkResult.getModel().getData() != null){
                return this.generateH5Code(linkResult.getModel().getData().getDsi(), sourceId, timeout);
            }

            LOGGER.error("generateH5CodeDirectly fail");
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new SystemError("generateH5CodeDirectly fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generateH5CodeDirectly error:{}", e.getMessage());
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<QrCodeResponse> generateMiniCodeDirectly(long activityId, long promotionId, String sourceId, int timeout){
        try {
            Result<LinkResponse> linkResult =  this.getLinkResult(activityId, promotionId, sourceId, timeout);
            if(linkResult != null && linkResult.getModel() != null && linkResult.getModel().getData() != null){
                return this.generateMiniCode(linkResult.getModel().getData().getDsi(), sourceId, timeout);
            }

            LOGGER.error("generateMiniCodeDirectly fail");
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new SystemError("generateMiniCodeDirectly fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generateMiniCodeDirectly error:{}", e.getMessage());
            return Result.Builder.<QrCodeResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<PosterResponse> generatePosterDirectly(long activityId, long promotionId, String sourceId, int timeout) {
        try {
            Result<LinkResponse> linkResult =  this.generateMiniLink(activityId, promotionId, sourceId, timeout);
            if(linkResult == null){
                return Result.Builder.<PosterResponse> builder().success(false).error(new BizError("get link fail")).model(null).build();
            }
            if(!linkResult.isSuccess()){
                return Result.Builder.<PosterResponse> builder().success(false).error(linkResult.getError()).model(null).build();
            }

            if(linkResult.getModel() != null && linkResult.getModel().getData() != null){
                return this.generatePoster(linkResult.getModel().getData().getDsi(), sourceId, timeout);
            }

            LOGGER.error("generatePosterDirectly fail");
            return Result.Builder.<PosterResponse> builder().success(false).error(new SystemError("generatePosterDirectly fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("generatePosterDirectly error:{}", e.getMessage());
            return Result.Builder.<PosterResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    public Result<LinkResponse> getLinkResult(long activityId, long promotionId, String sourceId, int timeout) {
        LOGGER.info("generateCodeDirectly start, activityId:{}, promotionId:{}, sourceId:{}",activityId, promotionId, sourceId);
        Result<LinkResponse> linkResult = this.generateMiniLink(activityId, promotionId, sourceId, timeout);
        if (linkResult == null) {
            return Result.Builder.<LinkResponse>builder().success(false).error(new BizError("get link fail")).model(null).build();
        }
        if (!linkResult.isSuccess()) {
            return Result.Builder.<LinkResponse>builder().success(false).error(linkResult.getError()).model(null).build();
        }
        return linkResult;
    }

    @Override
    public Result<OrderResponse> queryOrderList(long startTime, long endTime, OrderType type, int page, int size, int timeout) {

        if(page <= 0 || page > 100 || size <= 0 || size > 100){
            return Result.Builder.<OrderResponse> builder().success(false).error(new ParamError("分页参数不合法")).model(null).build();
        }

        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("pay_start_time", startTime);
            params.put("pay_end_time", endTime);
            params.put("page", page);
            params.put("size", size);
            if( type != null && OrderType.All != type ){
                params.put("type", type.getValue());
            }

            String resultStr = doGet(dunionClientConfig, orderListPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                OrderResponse model = new Gson().fromJson(resultStr, OrderResponse.class);
                return Result.Builder.<OrderResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("queryOrderList fail");
            return Result.Builder.<OrderResponse> builder().success(false).error(new SystemError("queryOrderList fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("queryOrderList error:{}", e.getMessage());
            return Result.Builder.<OrderResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<OrderCallbackResponse> mockOrderCallback(String dsi, String sourceId, OrderMockType type, int timeout)  {

        if(type == null){
            return Result.Builder.<OrderCallbackResponse> builder().success(false).error(new ParamError("分页参数不合法")).model(null).build();
        }

        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("dsi", dsi);
            params.put("source_id", sourceId);
            params.put("type", type.getValue());

            String resultStr = doGet(dunionClientConfig, orderMockPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                OrderCallbackResponse model = new Gson().fromJson(resultStr, OrderCallbackResponse.class);
                return Result.Builder.<OrderCallbackResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("mockOrderCallback fail");
            return Result.Builder.<OrderCallbackResponse> builder().success(false).error(new SystemError("mockOrderCallback fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("mockOrderCallback error:{}", e.getMessage());
            return Result.Builder.<OrderCallbackResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }

    }

    @Override
    public Result<OrderSelfQueryResponse> selfQueryOrder(String orderId, int timeout) {
        try {
            TreeMap<String, Object> params = new TreeMap<>();
            params.put("order_id", orderId);

            String resultStr = doGet(dunionClientConfig, orderSelfQueryPath, timeout, params);
            if (resultStr != null && !resultStr.equals("")) {
                OrderSelfQueryResponse model = new Gson().fromJson(resultStr, OrderSelfQueryResponse.class);
                return Result.Builder.<OrderSelfQueryResponse> builder().success(true).error(null).model(model).build();
            }

            LOGGER.error("selfQueryOrder fail");
            return Result.Builder.<OrderSelfQueryResponse> builder().success(false).error(new SystemError("selfQueryOrder fail")).model(null).build();
        } catch (Exception e) {
            LOGGER.error("selfQueryOrder error:{}", e.getMessage());
            return Result.Builder.<OrderSelfQueryResponse> builder().success(false).error(new BizError(e.getMessage())).model(null).build();
        }
    }
}
